//
//  MapView.m
//  SlashEM
//
//  Created by dirk on 1/18/10.
//  Copyright 2010 Dirk Zimmermann. All rights reserved.
//

//  This file is part of Slash'EM.
//
//  Slash'EM is free software: you can redistribute it and/or modify
//  it under the terms of the GNU General Public License as published by
//  the Free Software Foundation, version 2 of the License only.
//
//  Slash'EM is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU General Public License for more details.
//
//  You should have received a copy of the GNU General Public License
//  along with Slash'EM.  If not, see <http://www.gnu.org/licenses/>.

#import "MapView.h"
#import "NhMapWindow.h"
#import "TileSet.h"

@implementation MapView

- (id)initWithFrame:(CGRect)frame {
    if (self = [super initWithFrame:frame]) {
		self.multipleTouchEnabled = YES;
		tileSize = CGSizeMake(32.0f, 32.0f);
		maxTileSize = CGSizeMake(32.0f, 32.0f);
		minTileSize = CGSizeMake(8.0f, 8.0f);
		// load tileset
		UIImage *tilesetImage = [UIImage imageNamed:@"gltile32.png"];
		TileSet *tileSet = [[TileSet alloc] initWithImage:tilesetImage tileSize:CGSizeMake(32.0f, 32.0f)];
		[TileSet setInstance:tileSet];
		
    }
    return self;
}

- (void)drawRect:(CGRect)rect {
	NhMapWindow *map = (NhMapWindow *) [NhWindow mapWindow];
	if (map) {
		CGContextRef ctx = UIGraphicsGetCurrentContext();
	
		// switch to right-handed coordinate system (quartz)
		CGContextTranslateCTM(ctx, 0.0f, self.bounds.size.height);
		CGContextScaleCTM(ctx, 1.0f, -1.0f);
		
		// since this coordinate system is right-handed, each tile starts above left
		// and draws the area below to the right, so we have to be one tile height off
		CGPoint start = CGPointMake(clipOffset.x+panOffset.x,
									self.bounds.size.height-tileSize.height-clipOffset.y-panOffset.y);
		
		// black background to indicate map bounds
		float mapBackground[] = { 0.0f, 0.0f, 0.0f, 1.0f };
		CGContextSetFillColor(ctx, mapBackground);
		CGRect fillRect = CGRectMake(start.x, start.y+tileSize.height, tileSize.width*COLNO, -tileSize.height*ROWNO);
		//fillRect = CGRectInset(fillRect, -5.0f, -5.0f);
		CGContextFillRect(ctx, fillRect);

		for (int j = 0; j < ROWNO; ++j) {
			for (int i = 0; i < COLNO; ++i) {
				CGPoint p = CGPointMake(start.x+i*tileSize.width,
										start.y-j*tileSize.height);
				CGRect r = CGRectMake(p.x, p.y, tileSize.width, tileSize.height);
				if (CGRectIntersectsRect(r, rect)) {
					int ochar, ocolor;
					unsigned int special;
					int glyph = [map glyphAtX:i y:j];
					if (glyph) {
						mapglyph(glyph, &ochar, &ocolor, &special, i, j);
						CGImageRef tileImg = [[TileSet instance] imageForGlyph:glyph];
						CGContextDrawImage(ctx, r, tileImg);
					}
					// indicate tiles (might be useful for direction?)
//					float rectColor[] = { 0.5f, 0.5f, 0.5f, 1.0f };
//					CGContextSetStrokeColor(ctx, rectColor);
//					CGContextStrokeRect(ctx, r);
				}
			}
		}
	}
}

- (void)layoutSubviews {
	[super layoutSubviews];
	[self cliparoundX:clipX y:clipY];
}

- (void)cliparoundX:(int)x y:(int)y {
	clipX = x;
	clipY = y;
	CGPoint center = CGPointMake(self.bounds.size.width/2,
								 self.bounds.size.height/2);
	CGPoint playerPos = CGPointMake(x*tileSize.width, y*tileSize.height);

	// offset is the translation to get player to the center
	// note how this gets corrected about tileSize/2 to center player tile
	clipOffset = CGPointMake(center.x-playerPos.x-tileSize.width/2, center.y-playerPos.y-tileSize.height/2);
}

- (void) moveAlongVector:(CGPoint)d {
	panOffset.x += d.x;
	panOffset.y += d.y;
}

- (void) resetPanOffset {
	panOffset = CGPointMake(0.0f, 0.0f);
}

- (void) zoom:(CGFloat)d {
	d /= 5;
	CGSize originalSize = tileSize;
	tileSize.width += d;
	tileSize.width = round(tileSize.width);
	tileSize.height = tileSize.width;
	if (tileSize.width > maxTileSize.width) {
		tileSize = maxTileSize;
	} else if (tileSize.width < minTileSize.width) {
		tileSize = minTileSize;
	}
	CGFloat aspect = tileSize.width / originalSize.width;
	panOffset.x *= aspect;
	panOffset.y *= aspect;
	[self cliparoundX:clipX y:clipY];
	[self setNeedsDisplay];
}

- (BOOL)panned {
	return panOffset.x != 0 || panOffset.y != 0;
}

- (void)tilePositionX:(int *)px y:(int *)py fromPoint:(CGPoint)p {
	p.x -= panOffset.x;
	p.y -= panOffset.y;
	p.x -= clipOffset.x;
	p.y -= clipOffset.y;
	p.x -= tileSize.width/2;
	p.y -= tileSize.height/2;
	*px = roundf(p.x / tileSize.width);
	*py = roundf(p.y / tileSize.height);
}

- (void)dealloc {
    [super dealloc];
}

@end
